package ui.helpers;

import core.Database;
import core.DatabaseTable;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.border.Border;
import javax.swing.border.LineBorder;

import org.apache.log4j.Logger;
import ui.ApplicationWindow;


/**
 * Displays the {@link DatabaseTable}s as {@link JTable}s within a {@link JPanel}
 * providing an easier way for the user to have a view of the tables and make changes
 *
 * @author Sakis Vtdk <sakis.vtdk@gmail.com>
 */
public class DrawPanel extends javax.swing.JPanel {

	/**
	 * Creates new form DrawPanel
	 */
	public DrawPanel() {
		initComponents();
		setLayout(new WrapLayout());
		this.setComponentPopupMenu(DrawPanelPopup);
	}

	/**
	 * This method is called from within the constructor to initialize the form.
	 * WARNING: Do NOT modify this code. The content of this method is always
	 * regenerated by the Form Editor.
	 */
	@SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        DrawPanelPopup = new javax.swing.JPopupMenu();
        newTableItem = new javax.swing.JMenuItem();
        newTableItem.addActionListener(new NewTableListener());

        newTableItem.setText("Add Table");
        DrawPanelPopup.add(newTableItem);

        setLayout(null);
    }// </editor-fold>//GEN-END:initComponents
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JPopupMenu DrawPanelPopup;
    private javax.swing.JMenuItem newTableItem;
    // End of variables declaration//GEN-END:variables


	/**
	 * Creates a {@link JTable} from a {@link DatabaseTable} 
	 * and adds it to the <code>_tablesList</code>
	 * 
	 * @param dbTable The {@link DatabaseTable} to be added
	 */
	private void addTable(DatabaseTable dbTable)
	{
		log.trace("Adding table "+ dbTable.getName() +" to DrawPanel...");

		//create the table
		JTable table = new JTable(new DbTableViewModel(dbTable));
		table.setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS);

		//add a mouseListener
		table.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) 
			{
				JTable tbl = (JTable) e.getSource();
				String columnName = tbl.getColumnName(tbl.getSelectedColumn());
				int tableId = getScrollPaneIndexByName(columnName);

				highlightTable(tableId);
				ApplicationWindow.getApplicationWindow().selectItemInJtree(columnName);

				//get the selected item
				String selection = (String) tbl.getValueAt(tbl.getSelectedRow(), tbl.getSelectedColumn());
				ApplicationWindow.getApplicationWindow().selectItemInJtree(selection);

				if(e.getClickCount() == 2)
				{
					//check if the clicked value was "new column"
					if(selection.equals(DbTableViewModel.NEW_COLUMN_COMMAND))
					{
						NewColumnListener colListener = new NewColumnListener();
						colListener.createNewColumn(tableId);
					}
					else
					{
						ApplicationWindow.getApplicationWindow().selectItemInJtree(selection);
					}
					
				}
			}
		});


		//create the scrollPane
		JScrollPane scrollPaneContainer = new JScrollPane(table);
		scrollPaneContainer.setName(dbTable.getName());
		scrollPaneContainer.setPreferredSize(new Dimension(_initialWidth, _initialHeight));
		scrollPaneContainer.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e)
			{
				JScrollPane scrollPane = (JScrollPane) e.getSource();
				String scrollPaneName = scrollPane.getName();
				int paneId = getScrollPaneIndexByName(scrollPaneName);

				highlightTable(paneId);	
				ApplicationWindow.getApplicationWindow().selectItemInJtree(scrollPaneName);
			}
				
		});



		//add it in the arraylist
		_tablesList.add(scrollPaneContainer);
	}

	/**
	 * Updates the <code>_tablesList</code> getting the tables from the {@link Database}
	 */
	private void updateTablesList()
	{
		//clear the tables list fist
		_tablesList.clear();

		//add the tables
		for(DatabaseTable table : Database.getDatabase().getTables())
		{
			addTable(table);
		}
	}

	private int getScrollPaneIndexByName(String scrollPaneName)
	{
		for(int i = 0; i < _tablesList.size(); i++)
		{
			if(_tablesList.get(i).getName().equals(scrollPaneName))
			{
				return i;
			}
		}

		return -1;
	}

	/**
	 * Refreshes components within the {@link DrawPanel}
	 */
	public void refresh()
	{
		//remove everything from the container
		removeAll();

		//update the table list
		updateTablesList();

		//add the tables
		for(JScrollPane tmpScrollPane : _tablesList)
		{
			add(tmpScrollPane);
		}

		//revalidate the container
		revalidate();
	}

	/**
	 * Highlights the given table
	 * 
	 * @param tableId The id of the table to be highlighted
	 */
	public void highlightTable(int tableId)
	{
		//Un-highlight the previous table (if there is one)
		if(_lastTableSelected != -1)
		{
			unhighlightTable(_lastTableSelected);
		}

		log.trace("Highliting table: "+ tableId);

		//highlight the table
		((JScrollPane)getComponent(tableId)).setBorder(_highlightBorder);
		revalidate();

		//set the current table as the last selection
		_lastTableSelected = tableId;
	}

	/**
	 * Un-highlights the given table. This method is called by <code>highlightTable()</code>
	 * method to make sure only one table is highlighted at a time.
	 * 
	 * @param tableId The id of the table to be un-highlighted
	 */
	private void unhighlightTable(int tableId)
	{
		((JScrollPane)getComponent(tableId)).setBorder(_defaultBorder);
	}


	/**
	 * An <code>ArrayList</code> of <code>JScrollPane</code>s containing <code>JTable</code>s
	 */
	private ArrayList<JScrollPane> _tablesList = new ArrayList<JScrollPane>();

	/**
	 * The initial width of the <code>JScrollPane</code>
	 */
	private final int _initialWidth = 150;

	/**
	 * The initial height of the <code>JScrollPane</code>
	 */
	private final int _initialHeight = 200;

	/**
	 * The border which will be used to highlight the selected table
	 */
	private final Border _highlightBorder = new LineBorder(new Color(0, 153, 204), 3, true);

	/**
	 * The default border of the tables
	 */
	private final Border _defaultBorder = new LineBorder(Color.black, 1, false);

	/**
	 * The last selected table. Used to un-highlight it when a new table is selected
	 */
	private int _lastTableSelected = -1;
	
	/**
	 * Logger instance
	 */
	private static Logger log = Logger.getLogger(DrawPanel.class);
}
